/* GA_IPD2.java
 * CAP 5512
 * HW3, group 2
 * 
 * Date/other stuff/etc.
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;

public class GA_TLP2 extends FitnessFunction
{

   private String outputFile;
   private String net, input_routes, trafficlight, output;
   private Process p;
   private static Random randomGenerator = new Random();
   private int populationCount;

   public GA_TLP2()
   {
      name = "GA_TLP2";
      randomGenerator.setSeed(Parameters.seed);
      populationCount = 0;
   }

   public void doRawFitness(Chromo X)
   {
      int time;
      float waitingTime, meanTravelTime;
      float[] occupancy;
      String s = null;

      //create the new traffic lights based on Chromo
      CreateXMLFile2 CXF = new CreateXMLFile2(X);
      time = CXF.getTime();

      //run the SUMO simulation
      try
      {
         p = Runtime.getRuntime().exec(GenerateSUMOExcutionString());
      } catch (IOException e)
      {
         e.printStackTrace();
      }

      ProcessHandler inputStream = new ProcessHandler(p.getInputStream(), "INPUT");
      ProcessHandler errorStream = new ProcessHandler(p.getErrorStream(), "ERROR");
      inputStream.start();
      errorStream.start();

      try
      {
         p.waitFor();
      } catch (InterruptedException e)
      {
         e.printStackTrace();
      }

      //Process output
      ProcessXMLOutput xmlOut = new ProcessXMLOutput();

      //call getter methods
      waitingTime = xmlOut.getWaitingTime();
      meanTravelTime = xmlOut.getMeanTravelTime();

      //TODO - get more than 1 lane ID out
      occupancy = xmlOut.getOccupancy();

      //Calculate the fitness for the aggregate of the timing lights based on occupancy

      //assign fitness
      X.rawFitness = X.meanWaitingTimeAllLanes 
                     + X.meanOccupancy[Constant.EAST_FORWARD]
                     + X.meanOccupancy[Constant.EAST_LEFT_TURN]
                     + X.meanOccupancy[Constant.EAST_RIGHT_TURN]
                     + X.meanOccupancy[Constant.NORTH_FORWARD]
                     + X.meanOccupancy[Constant.NORTH_LEFT_TURN]
                     + X.meanOccupancy[Constant.NORTH_RIGHT_TURN]
                     + X.meanOccupancy[Constant.SOUTH_FORWARD]
                     + X.meanOccupancy[Constant.SOUTH_LEFT_TURN]
                     + X.meanOccupancy[Constant.SOUTH_RIGHT_TURN]
                     + X.meanOccupancy[Constant.WEST_FORWARD]
                     + X.meanOccupancy[Constant.WEST_LEFT_TURN]
                     + X.meanOccupancy[Constant.WEST_RIGHT_TURN];
;

      //Store simulation statistics
      X.meanWaitingTimeAllLanes = xmlOut.getWaitingTime();
      X.meanTravelTimeAllLanes  = xmlOut.getMeanTravelTime();
      X.meanTravelTime          = xmlOut.getLaneMeanTravelTime();
      X.meanDensity             = xmlOut.getMeanDensity();
      X.meanOccupancy           = xmlOut.getMeanOccupancy();
      X.meanWaitingTime         = xmlOut.getMeanWaitingTime();
      X.meanSpeed               = xmlOut.getMeanSpeed();
      X.vehiclesEntered         = xmlOut.getVehiclesEntered();
      X.vehiclesLeft            = xmlOut.getVehiclesLeft();
      X.meanNumberOfVehicles               = xmlOut.getAvgNumVehicles();
      X.meanTrafficVolumeCarsPerHour       = xmlOut.getAvgTrafficVolumeCarsPerHour();
      X.meanTrafficVolumeAtExitCarsPerHour = xmlOut.getAvgTrafficVolumeExitingLaneCarsPerHour();

      //System.out.println("Done with fitness " + waitingTime + "   meanTravelTime " + meanTravelTime);
   }

//	public void doPrintGenes(Chromo X, FileWriter output) throws java.io.IOException{
//
//		// Print the genes in reverse order. Gene 0 is stored in the LSB position, 
//		// thus, if you print it starting with that gene, the bits won't reflect the actual
//		// ordering within the representation
//		for (int i=Parameters.numGenes-1; i>=0; i--){
//			Hwrite.right(X.getGeneAlpha(i), Parameters.geneSize+2, output);
//		}
//		output.write("  RawFitness");
//		output.write("\n        ");
//		for (int i=Parameters.numGenes-1; i>=0; i--){
//			Hwrite.right(X.getIntGeneValue(i), Parameters.geneSize+2, 4, output);
//		}
//		Hwrite.right(X.rawFitness,12, 6, output);
//		output.write("\n\n");
//		return;
//	}
   public void doPrintGenes(Chromo X, FileWriter output) throws java.io.IOException
   {

      // Print the genes in reverse order. Gene 0 is stored in the LSB position,
      // thus, if you print it starting with that gene, the bits won't reflect the actual
      // ordering within the representation
      for (int i = 0; i < Parameters.numGenes; i++)
      {
         Hwrite.right("\""+X.getGeneAlpha(i)+"\"", 100, output);
      }
      output.write(",");
      for (int i = 0; i < Parameters.numGenes; i++)
      {
         Hwrite.right(X.getIntGeneValue(i), 30, 4, output);
      }
      output.write(",");
      Hwrite.right(X.rawFitness, 12, 6, output);
      return;
   }


   //Generate Output file
   private String GenerateSUMOExcutionString()
   {
      String randomRouteFile = "";
      int randomFileNumber = 0;

      //Keeps the route size
      if (this.populationCount++ > Parameters.popSize)
      {
         randomFileNumber = this.randomGenerator.nextInt(4);
         this.populationCount = 0;
      }



      if (Parameters.isMacOS)
      {
         net = Parameters.sumoNetworkRoutePath + Parameters.sumoNetworkFile;

         if (Parameters.sumoRouteFile.equals("RANDOM"))
         {
            switch (randomFileNumber)
            {
               case 0:
                  randomRouteFile = "random1.rou.xml";
                  break;
               case 1:
                  randomRouteFile = "random2.rou.xml";
                  break;
               case 2:
                  randomRouteFile = "random3.rou.xml";
                  break;
               case 3:
                  randomRouteFile = "random4.rou.xml";
                  break;
               default:
                  System.out.println("\n\nERROR-No file for random int\n");
            }

            input_routes = Parameters.sumoNetworkRoutePath + randomRouteFile;
         } else
         {
            input_routes = Parameters.sumoNetworkRoutePath + Parameters.sumoRouteFile;
         }

         trafficlight = Parameters.sumoNetworkRoutePath + Parameters.sumoAdditionalParamFile;
         output = Parameters.sumoOutputPath + Parameters.sumoOutputFile;

         outputFile = Parameters.sumoBinPath + "sumo"
                 + " -b " + Parameters.sumoBeginTime
                 + " -e " + Parameters.sumoEndTime
                 + " -n " + net
                 + " -r " + input_routes
                 + " -a " + trafficlight
                 + " --emissions-output " + output
                 + " --time-to-teleport -1"; //Forces SUMO not to teleport vehicles

      } else
      {//Windows Machine
         net = "\"" + Parameters.sumoNetworkRoutePath + Parameters.sumoNetworkFile + "\"";

         if (Parameters.sumoRouteFile.equals("RANDOM"))
         {
            switch (randomFileNumber)
            {
               case 0:
                  randomRouteFile = "random1.rou.xml";
                  break;
               case 1:
                  randomRouteFile = "random2.rou.xml";
                  break;
               case 2:
                  randomRouteFile = "random3.rou.xml";
                  break;
               case 3:
                  randomRouteFile = "random4.rou.xml";
                  break;
               default:
                  System.out.println("\n\nERROR-No file for random int\n");
            }

            input_routes = "\"" + Parameters.sumoNetworkRoutePath + randomRouteFile + "\"";
         } else
         {
            input_routes = "\"" + Parameters.sumoNetworkRoutePath + Parameters.sumoRouteFile + "\"";
         }

         trafficlight = "\"" + Parameters.sumoNetworkRoutePath + Parameters.sumoAdditionalParamFile + "\"";
         output = "\"" + Parameters.sumoOutputPath + Parameters.sumoOutputFile + "\"";

         outputFile = "\"" + Parameters.sumoBinPath + "sumo.exe" + "\""
                 + " -b " + Parameters.sumoBeginTime
                 + " -e " + Parameters.sumoEndTime
                 + " -n " + net
                 + " -r " + input_routes
                 + " -a " + trafficlight
                 + " --emissions-output " + output
                 + " --time-to-teleport -1"; //Forces SUMO not to teleport vehicles.


      }//end if MAC or Windows

      //System.out.println("\n" + outputFile);
      return outputFile;
   }//end GenerateSUMOExcutionString
}
